package org.gwt.grin.rebind;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.gwt.grin.client.Segment;
import org.gwt.grin.client.features.Group;
import org.gwt.grin.rebind.input.SERCHandler;

public class ShowBuilder {

	private Map<String, SESegment> namedSegments = new HashMap<String, SESegment>();
	private Map<String, SEFeature> namedFeatures = new HashMap<String, SEFeature>();
	private Map<String, SERCHandler> namedRCHandlers = new HashMap<String, SERCHandler>();
	private Map<String, SECommand> namedCommands = new HashMap<String, SECommand>();

	// Contains all segments, features, RC handlers and commands
	List<SESegment> allSegments = new ArrayList<SESegment>();
	List<SEFeature> allFeatures = new ArrayList<SEFeature>();
	List<SERCHandler> allRCHandlers = new ArrayList<SERCHandler>();
	List<SECommand> allCommands = new ArrayList<SECommand>();
	// private ArrayList<SENode> allNodes = new ArrayList<SENode>();

	private List<String> exportedSegments = null;
	private List<String> exportedFeatures = null;
	// private List<String> exportedRCHandlers = null;
	private List<String> exportedNamedCommands = null;

	private Group showTopGroup = null;
	private Segment showTop = null;

	public ShowBuilder() {
		super();
	}

	/**
	 * Called when a "show_top" clause is encountered.
	 */
	public void setShowTop(String showTopName) throws IOException {
		if (this.showTop != null) {
			throw new IOException("Multiple show_top clauses");
		}
		// this.showTop = makeShowTopSegment(namedFeatures.get(showTopName));
	}

	/**
	 * Called when a new feature is encountered.
	 **/
	public void addFeature(String name, int line, SEFeature f)
			throws IOException {
		if (name != null) {
			if (namedFeatures.get(name) != null) {
				throw new IOException("Feature names \"" + name
						+ "\" already exists!");
			}
			namedFeatures.put(name, f);
		}
		allFeatures.add(f);
	}

	/**
	 * Called when a new segment is encountered.
	 **/
	public void addSegment(String name, int line, SESegment segment)
			throws IOException {
		if (name != null) {
			if (namedSegments.get(name) != null) {
				throw new IOException("Segment named \"" + name
						+ "\" already exists!");
			}
			namedSegments.put(name, segment);
		}
		allSegments.add(segment);
	}

	/**
	 * Called when a new named command is encountered.
	 */
	public void addNamedCommand(String name, int line, SECommand c)
			throws IOException {
		if (namedCommands.get(name) != null) {
			throw new IOException("Named command \"" + name
					+ "\" already exists.");
		}
		namedCommands.put(name, c);
	}

	/**
	 * Called when a new command is encountered.
	 **/
	public void addCommand(SECommand c, int line) throws IOException {
		allCommands.add(c);
		// addNode((SENode) command);
	}

	/**
	 * Called when a new remote control handler is encountered.
	 */
	public void addRCHandler(String name, int line, SERCHandler hand)
			throws IOException {
		if (name != null) {
			if (namedRCHandlers.get(name) != null) {
				throw new IOException("RC Handler named \"" + name
						+ "\" already exists.");
			}
			namedRCHandlers.put(name, hand);
		}
		allRCHandlers.add(hand);
		// addNode(hand)
	}

	/**
	 * Called when the exported clause is encountered. This is optional; if it's
	 * not called, then everything defaults to public visibility.
	 * <p>
	 * The segments, features and handlers may contain the wildcard character
	 * "*", which cannot be escaped.
	 */
	public void setExported(String[] segments, String[] features,
			String[] namedCommands) throws IOException {
		if (exportedSegments != null) {
			throw new IOException("Multiple exported clauses");
		}

		exportedSegments = Arrays.asList(segments);
		exportedFeatures = Arrays.asList(features);
		// exportedRCHandlers = Arrays.asList(handlers);
		exportedNamedCommands = Arrays.asList(namedCommands);
	}

	/**
	 * Look up a segment in the list of all named segments.
	 **/
	public SESegment getNamedSegment(String name) {
		return namedSegments.get(name);
	}

	/**
	 * Look up a command in the list of all named commands.
	 **/
	public SECommand getNamedCommand(String name) {
		return namedCommands.get(name);
	}

	/**
	 * Look up a feature in the list of all named features.
	 **/
	public SEFeature getNamedFeature(String name) {
		return namedFeatures.get(name);
	}

	/**
	 * Look up a RC handler in the list of all named RC handlers.
	 **/
	public SERCHandler getNamedRCHandler(String name) {
		return namedRCHandlers.get(name);
	}

	public void finishBuilding() {
		// TODO Auto-generated method stub

	}

	private static int counter = 0;

	public String buildUniqueName(Class<?> klass) {
		String nm = klass.getName();
		int i = nm.lastIndexOf('.');
		if (i >= 0) {
			nm = nm.substring(i + 1, nm.length());
		}
		return nm.toLowerCase() + counter++;
	}

}
